package com.cpit.platform.web.controller;

import java.util.*;

import com.cpit.platform.common.constant.LogConstant;
import com.cpit.platform.common.entity.TableDataQueryCondition;
import com.cpit.platform.common.utils.LogUtils;
import com.cpit.platform.common.utils.ResultUtil;
import com.cpit.platform.dto.OperLog;
import com.cpit.platform.service.OperLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.cpit.platform.common.entity.Result;
import com.cpit.platform.common.entity.TableJsonData;
import com.cpit.platform.common.entity.ZTreeNode;
import com.cpit.platform.dto.Organization;
import com.cpit.platform.log.LogOperator;
import com.cpit.platform.service.OrganizationService;

import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

@Controller
@RequestMapping(value = "/Organization")
public class OrganizationController {
	private String moduleNmae = "机构：";
	@Autowired
	private OrganizationService organizationService;
	@Autowired
	private OperLogService operLogService;
	private final String loggerName = this.getClass().getName();
	
	@ApiOperation(value="查询组织关系列表", notes="通过条件查询系统中的组织关系信息" + 
	"支持分页查询，支持模糊查询。")
	@ResponseBody
	@PreAuthorize("hasAuthority('queryOrganization')")
	@RequestMapping(value="/queryOrganization", method = RequestMethod.GET)  
	public List<Organization> queryOrganization(
			@ApiParam(value = "当前页数， 以1开始。") @RequestParam(value = "page", required = true, defaultValue = "1") int page, 
			@ApiParam(value = "当前页的内容长度。") @RequestParam(value = "size", required = true, defaultValue = "20") int size, 
			@ApiParam(value = "排序方式：asc为升序，desc为降序。") @RequestParam(value = "order", required = false, defaultValue = "asc") String order, 
			@ApiParam(value = "排序字段，与dto中声明的字段名称一致。") @RequestParam(value = "orderBy", required = false, defaultValue = "id") String orderBy, 
			@ApiParam(value = "模糊搜索的字符串，根据组织关系的名称字段进行模糊匹配。") @RequestParam(value = "orgName", required = false, defaultValue = "") String orgName,
			@ApiParam(value = "查询某组织机构的下级机构时指定的查询条件。该参数是某组织机构的code字段。") @RequestParam(value = "orgIdCondition", required = false, defaultValue = "") String orgIdCondition)  {
		return organizationService.findByCondition(page, size, order, orderBy, orgName, orgIdCondition);
	}  
	
	@ApiOperation(value="查询组织关系列表", notes="通过条件查询系统中的组织关系信息" + 
			"支持分页查询，支持模糊查询。")
		    @ApiImplicitParams({
		            @ApiImplicitParam(name = "cond", value = "JqGrid的条件对象，由JqGrid根据js参数自动封装。", required = true, dataType = "TableDataQueryCondition")
		    })
	@ResponseBody
	@PreAuthorize("hasAuthority('queryOrganization')")
	@RequestMapping(value="/queryOrganizationJqg", method = RequestMethod.GET)  
	public TableJsonData queryOrganizationJqg(TableDataQueryCondition cond)  {
		return organizationService.findByConditionJqg(cond);
	}  
	
	@ApiOperation(value="创建组织关系项目", notes="用户手工指定组织关系项目并创建，" + 
			"需要手动输入组织关系的详细信息，包括名称、描述，以及对应的父组织机构信息。一个组织机构有且只有一个父机构。")
		     @ApiImplicitParam(name = "data", value = "组织关系描述对象。", required = true, dataType = "Organization")
	@ResponseBody
	//@PreAuthorize("hasAuthority('createOrganization')")//有createOrganization组织关系的才能访问  
	@RequestMapping(value="/createOrganization", method = RequestMethod.POST)  
	public Result<Organization> createOrganization(@RequestBody Organization data) {
		try{
			if (StringUtils.isEmpty(data.getName()) || data.getParentId() == null) {
				return ResultUtil.error(Result.CODE_FAILED, "组织机构信息不全，请补充！");
			}
			organizationService.create(data);
			writeLog(LogConstant.OPER_CREATE, Result.CODE_SUCCESS,data.getName());
			return new Result<Organization>(Result.CODE_SUCCESS, "", data);
		} catch(Exception e) {
			writeLog(LogConstant.OPER_CREATE, Result.CODE_FAILED,e.getMessage());
			return new Result<Organization>(Result.CODE_FAILED, e.getMessage(), data);
		}
	}  
	
	@ApiOperation(value="修改组织关系项目", notes="用户手工指定组织关系项目并修改，" + 
			"需要手动输入组织关系的详细信息，包括名称、描述，以及对应的父组织机构信息。一个组织机构有且只有一个父机构。")
		     @ApiImplicitParam(name = "data", value = "组织关系描述对象。", required = true, dataType = "Organization")
	@ResponseBody
	@PreAuthorize("hasAuthority('modifyOrganization')")
	@RequestMapping(value="/modifyOrganization", method = RequestMethod.POST)  
	public Result<Organization> modifyOrganization(@RequestBody Organization data) {
		try{
			organizationService.modify(data);
			writeLog(LogConstant.OPER_MODIFY, Result.CODE_SUCCESS,data.getName());
			return new Result<Organization>(Result.CODE_SUCCESS, "", data);
		} catch(Exception e) {
			writeLog(LogConstant.OPER_MODIFY, Result.CODE_FAILED,e.getMessage());
			return new Result<Organization>(Result.CODE_FAILED, e.getMessage(), data);
		}
	}
	
	@ApiOperation(value="删除组织关系项目", notes="在系统中删除已经存在的组织关系项目，" + 
			"如果该组织关系被组织关系引用，则不允许删除。")
		     @ApiImplicitParam(name = "data", value = "组织关系描述对象。", required = true, dataType = "Organization")
	@ResponseBody
	@PreAuthorize("hasAuthority('deleteOrganization')")
	@RequestMapping(value="/deleteOrganization", method = RequestMethod.DELETE)  
	public Result<Organization> deleteOrganization(@RequestBody Organization data) {
		try{
			organizationService.delete(data);
			writeLog(LogConstant.OPER_DELETE, Result.CODE_SUCCESS,data.getName());
			return new Result<Organization>(Result.CODE_SUCCESS, "", data);
		} catch(Exception e) {
			writeLog(LogConstant.OPER_DELETE, Result.CODE_FAILED,e.getMessage());
			return new Result<Organization>(Result.CODE_FAILED, "", data);
		}
	}

	
	@ApiOperation(value="获取组织关系树结构", notes="获取组织关系树结构")
	@ResponseBody
	@PreAuthorize("hasAuthority('queryOrganization')")
	@RequestMapping(value="/queryOrganizationTree", method = RequestMethod.GET)  
	public ZTreeNode queryOrganizationTree() {
		try{
			LogOperator.debug(loggerName, "query org tree");
			List<Organization> orgLst = organizationService.findByConditionForTree(
					1, 1000, "", "", "", "");
//			TreeMap<Integer, Organization> tMap = new TreeMap<Integer, Organization>();
//			if(orgLst == null ||  orgLst.size() == 0) {
//				LogOperator.warn(loggerName, "query org tree, no org here");
//				return new ZTreeNode();
//			}
//			for(Organization org : orgLst) {
//				tMap.put(org.getId(), org);
//			}
//			LogOperator.debug(loggerName, "query org tree result: " + tMap);
			// recrusive data
			ZTreeNode rootNode = new ZTreeNode();
			TreeMap<Integer, List<Organization>> pIdToChildrenMap = new TreeMap<Integer, List<Organization>>();
			for(Organization o : orgLst) {
				int pid = o.getParentId();
				List<Organization> cLst = null;
				if(pIdToChildrenMap.containsKey(pid)) {
					cLst = pIdToChildrenMap.get(pid);
				} else {
					cLst = new ArrayList<Organization>();
					pIdToChildrenMap.put(pid, cLst);
				}
				cLst.add(o);
			}
			LogOperator.debug(loggerName, "p map is: " + pIdToChildrenMap);
			Organization rootOrg = pIdToChildrenMap.get(-1).get(0);
			rootNode = recruSiveCreateTree(rootOrg, pIdToChildrenMap);
			return rootNode;
		} catch(Exception e) {
			LogOperator.err(loggerName, "query org tree error", e);
			return null;
		}
	}

	@ApiOperation(value="获取组织关系树结构", notes="无鉴权获取组织关系树结构")
	@ResponseBody
	@PreAuthorize("hasAuthority('queryOrganization')")
	@RequestMapping(value="/queryOrganizationTree/unsafe", method = RequestMethod.GET)
	public ZTreeNode queryOrganizationTreeUnsafe() {
		try{
			LogOperator.debug(loggerName, "query org tree");
			List<Organization> orgLst = organizationService.findByConditionForTreeWithoutSecurity(
					1, 1000, "", "", "", "");
//			TreeMap<Integer, Organization> tMap = new TreeMap<Integer, Organization>();
//			if(orgLst == null ||  orgLst.size() == 0) {
//				LogOperator.warn(loggerName, "query org tree, no org here");
//				return new ZTreeNode();
//			}
//			for(Organization org : orgLst) {
//				tMap.put(org.getId(), org);
//			}
//			LogOperator.debug(loggerName, "query org tree result: " + tMap);
			// recrusive data
			ZTreeNode rootNode = new ZTreeNode();
			TreeMap<Integer, List<Organization>> pIdToChildrenMap = new TreeMap<Integer, List<Organization>>();
			for(Organization o : orgLst) {
				int pid = o.getParentId();
				List<Organization> cLst = null;
				if(pIdToChildrenMap.containsKey(pid)) {
					cLst = pIdToChildrenMap.get(pid);
				} else {
					cLst = new ArrayList<Organization>();
					pIdToChildrenMap.put(pid, cLst);
				}
				cLst.add(o);
			}
			LogOperator.debug(loggerName, "p map is: " + pIdToChildrenMap);
			Organization rootOrg = pIdToChildrenMap.get(-1).get(0);
			rootNode = recruSiveCreateTree(rootOrg, pIdToChildrenMap);
			return rootNode;
		} catch(Exception e) {
			LogOperator.err(loggerName, "query org tree error", e);
			return null;
		}
	}
	
	protected ZTreeNode recruSiveCreateTree(Organization rootOrg, Map<Integer, List<Organization>> pIdToChildrenMap) {
		Boolean isParent = false;
		if(pIdToChildrenMap.containsKey(rootOrg.getId())) {
			isParent = true;
		}
		ZTreeNode node = new ZTreeNode(String.valueOf(rootOrg.getId()), 
				String.valueOf(rootOrg.getParentId()), rootOrg.getName(),
				 isParent, ZTreeNode.NODE_TYPE_ORGANIZATION);
		node.setOrganizationCode(rootOrg.getCode());
		if(isParent) {
			List<Organization> cLst = pIdToChildrenMap.get(rootOrg.getId());
			for(Organization o : cLst) {
				ZTreeNode c = recruSiveCreateTree(o, pIdToChildrenMap);
				node.getChildren().add(c);
			}
		}
		return node;
	}
	private  void  writeLog(String op,String result, String detail){
		OperLog operLog = LogUtils.createOperLog(LogConstant.MODULE_CONFIG,op,result,moduleNmae + detail);
		operLogService.writeLog(operLog);
	}
}
